import json
import re

from django.shortcuts import render
from apps.users.models import User
# Create your views here.
from django.views import View
from django.http.response import JsonResponse
from django_redis import get_redis_connection


class UsernameCountView(View):

    def get(self, request, username):
        count = User.objects.filter(username=username).count()

        return JsonResponse({'count': count})


class MobileCountView(View):

    def get(self, request, mobile):
        count = User.objects.filter(mobile=mobile).count()

        return JsonResponse({'count': count})


class RegisterView(View):

    def post(self, request):

        # 1、接收参数
        # 1.1 获取bytes数据
        body_bytes = request.body
        # 1.2 解码为字符串
        str_data = body_bytes.decode()
        import json
        # 1.3 转化为字典
        data = json.loads(str_data)

        # 2.提取参数
        # 用户名密码确认密码，同意协议，图片验证码，短信验证码
        username = data.get('username')
        password = data.get('password')
        password2 = data.get('password2')
        mobile = data.get('mobile')
        sms_code = data.get('sms_code')
        allow = data.get('allow')

        # 链接redis数据库
        redis_cli = get_redis_connection('code')
        redis_mible = redis_cli.get(mobile)

        redis_cli.delete('mobile')

        # 3. 验证参数 [我们不相信前端提交的任何数据]
        # 3.1 这5个参数都要有数据
        # all[变量名,变量名,...] 只要不是None或者False  就返回True
        if not all([username, password, password2, mobile, allow]):
            return JsonResponse({'code': 400, "errmsg": "必填字段为空"})
        # 3.2 用户名需要符合规则 用户名也不能重复[不重复写了]
        if not re.match('[0-9A-Za-z_]{5,20}', username):
            return JsonResponse({'code': 400, 'errmsg': '用户名不符合规则'})
        # 3.3 密码符合规则
        if not re.match('[a-zA-Z0-9_]{8,20}', password):
            return JsonResponse({'code': 400, "errmsg": '密码长度为8-20位'})
        # 3.4 密码和确认密码一致
        if password != password2:
            return JsonResponse({'code': 400, "errmsg": '两次密码不一致'})
        # 3.5 手机号需要符合规则 手机号也不能重复[作业]
        if not re.match('1[3-9]\d{9}', mobile):
            return JsonResponse({'code': 400, "errmsg": '手机号格式不正确'})

        if not re.match('^[0-9]{6}$', sms_code):
            return JsonResponse({'code': 400, 'errmsg': '短信验证码错误!!!'})

        # 判断手机验证码是否过期
        if redis_mible is None:
            return JsonResponse({'code': 400, 'errmsg': '短信验证码已过期'})

        # 判断手机验证码是否正确
        if sms_code != redis_mible.decode():
            return JsonResponse({"code": 400, 'errmsg': '短信验证码不正确'})

        if not allow:
            return JsonResponse({'code': 400, 'errmsg': '111'})
        # 4. 数据入库
        # User().save()
        # User.objects.create()
        # 以上这2种方式 都是可以的. 但是会有一个问题
        # 密码没有加密

        # 要对密码进行加密
        # Django自带的用户模型中 有对密码加密的方法
        # create_user
        user = User.objects.create_user(
            username=username,
            password=password,
            mobile=mobile
        )
        from django.contrib.auth import login

        # 5.状态保持(session redis) 单独讲
        # 设置session的基本操作
        # request.session['id']=user.id
        # request.session['username']=user.username
        # request.session['mobile']=user.mobile

        # 状态保持
        # login(请求对象,User实例对象)
        login(request, user)

        return JsonResponse({'code': 0, 'errmsg': 'ok'})


class LoginView(View):
    def post(self, request):
        data = json.loads(request.body.decode())

        username = data.get('username')
        password = data.get('password')
        remembered = data.get('remembered')

        # if not re.match('[0-9a-zA-Z_]{5,20}', username):
        #     return JsonResponse({'code': 400, 'errmsg': '用户名不符合规范'})

        if re.match('1[3-9]\d{9}', username):
            User.USERNAME_FIELD = 'mobile'

        # if re.match('[0-9]{1,}', username):
        #
        #     User.USERNAME_FIELD = 'password'
        # from django.contrib.auth import authenticate
        # user = authenticate(username=username, password=password)
        else:
            User.USERNAME_FIELD = 'username'

        # 方式1
        # if not all([username, password]):
        #     return JsonResponse({'code':400,'errmsg':'参数不全'})
        # try:
        #     user = User.objects.get(username=username)
        # except User.DoesNotExist:
        #     return JsonResponse({'code': 400, 'errmsg': '用户名或密码错误'})
        #
        # else:
        #     if not user.check_password(password):
        #         return JsonResponse({'code': 400, 'errmsg': '用户名或密码错误'})

        # 方式2
        if not all([username, password]):
            return JsonResponse({'code': 400, 'errmsg': '参数不全'})

        from django.contrib.auth import authenticate

        user = authenticate(username=username, password=password)

        if user is None:
            return JsonResponse({'code': 400, 'errmsg': '用户名或密码错误'})

        from django.contrib.auth import login
        login(request, user)

        if remembered:
            request.session.set_expiry(None)

        else:
            request.session.set_expiry(0)

        response = JsonResponse({'code': 0, 'errmsg': 'ok'})
        response.set_cookie('username', user.username, max_age=3600 * 24 * 15)
        return response


class LogoutView(View):
    def delete(self, request):
        from django.contrib.auth import logout

        logout(request)

        response = JsonResponse({'code': 0, 'errmsg': '退出成功'})
        response.delete_cookie('username')

        return response


"""
需求:         用户要访问个人中心页面


前端:
            用户点击个人中心.  前端要发送一个 axios请求.这个请求会携带cookie信息. cookie信息中有 sessionid

服务器:
        请求
                        GET         info/
        业务逻辑
                    1. 获取登录用户的信息
                    2. 组织为JSON数据
                    3. 返回响应
        响应
                    {
                        'code': 0, 
                        'errmsg': '个人中心',
                         "info_data":{
                                "username":"itcast",
                                "mobile": "18310820688",
                                "email": "",
                                "email_active": 'true'
                            }
                    }

"""

from utils.user import LoginRequiredJSONMixin


class UserCenterView(LoginRequiredJSONMixin, View):
    def get(self, request):
        user = request.user
        user_info = {
            'username': user.username,
            'mobile': user.mobile,
            'email': user.email,
            'email_active': user.email_active
        }

        return JsonResponse({'code': 0, 'errmsg': 'ok', 'info_data': user_info})


from utils.user import LoginRequiredJSONMixin


class EmailView(LoginRequiredJSONMixin, View):
    def put(self, request):
        # 1. 判断用户是否登录
        # 2. 接收参数
        data = json.loads(request.body.decode())
        # 3. 提取参数
        email = data.get('email')
        # 4. 验证参数
        if not re.match('[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}', email):
            return JsonResponse({'code': 400, 'errmsg': '邮箱格式不正确'})
        # 5. 更新参数
        request.user.email = email
        request.user.save()

        # from django.core.mail import send_mail
        # #subject,  主题
        # subject = '美多商城激活邮件'
        # # message,  消息，内容
        # message =''
        # # from_email,  发件人
        # from_email = '美多商城官方邮箱<rileyle@163.com>'
        # # recipient_list 收件人列表
        # recipient_list = [email]
        # html_message = '<a href="http://www.baidu.com">百度</a>'
        # send_mail(subject,
        #           message,
        #           from_email,
        #           recipient_list,
        #           html_message=html_message)
        # 邮件加密
        from apps.users.common import generic_email_token
        token = generic_email_token(email, request.user.id)

        verify_url = 'http://www.meiduo.site:8080/success_verify_email.html?token=%s' % token

        from celery_tasks.email.tasks import celery_send_email
        celery_send_email.delay(email, verify_url)
        return JsonResponse({'code': 0})


class EmailVerificationView(View):
    def put(self, request):
        # 1. 接收请求
        data = request.GET
        # 2. 提取数据
        token = data.get('token')
        # 3. 对数据进行解密操作
        from apps.users.common import chect_email_token
        data = chect_email_token(token)
        # 4. 判断有没有user_id
        if data is None:
            return JsonResponse({'code': 400, 'errmsg': '过期了'})
        # 5. 如果没有则说明 token过期了
        # 6. 如果有,则查询用户信息
        email = data.get('email')
        user_id = data.get('user_id')
        try:
            user = User.objects.get(email=email, id=user_id)
        except User.DoesNotExist:
            return JsonResponse({'code': 400, 'errmsg': '用户不存在'})
        # 7. 改变用户的邮箱激活状态
        user.email_active = True
        user.save()
        # 8. 返回响应
        return JsonResponse({'code': 0, 'errmsg': 'ok'})


"""

增删改查

web 
    请求 
        业务逻辑[增删改查] 
    响应


增
    1. 接收参数
    2. 提取参数
    3. 验证参数
    4. 数据入库
    5. 返回响应   
删
    1. 获取要删除数据id  指定删除某一[n]条数据   [id指定哪些数据]
    2. 根据id查询数据
    3. 删除数据[物理删除/逻辑删除]
    4. 返回响应
改
    1. 获取要更新[修改]数据id  指定修改某一[n]条数据   [id指定哪些数据]
    2. 根据id查询数据
    3. 接收参数
    4. 提取参数
    5. 验证参数
    6. 数据更新
    7. 返回响应   
查
    1.根据需求查询数据
    2.将对象转换为字典数据
    3.返回响应
"""

from apps.users.models import Address

from utils.user import LoginRequiredJSONMixin


class CreateAddressView(LoginRequiredJSONMixin, View):
    def post(self, request):

        count = Address.objects.filter(user=request.user, is_deleted=False).count()

        if count >= 20:
            return JsonResponse({'code': 0, 'errmsg': '新增地址超过上限'})
        # 1, 接收参数
        json_dict = json.loads(request.body.decode())
        # 2. 提取参数
        receiver = json_dict.get('receiver')
        province_id = json_dict.get('province_id')
        city_id = json_dict.get('city_id')
        district_id = json_dict.get('district_id')
        place = json_dict.get('place')
        mobile = json_dict.get('mobile')
        tel = json_dict.get('tel')
        email = json_dict.get('email')

        # 3, 验证参数
        if not all([receiver, province_id, city_id, district_id, place, mobile]):
            return JsonResponse({'code': 400, 'errmsg': '参数缺少'})

        # 4. 数据入库
        address = Address.objects.create(
            user=request.user,
            title=receiver,
            receiver=receiver,
            province_id=province_id,
            city_id=city_id,
            district_id=district_id,
            place=place,
            mobile=mobile,
            tel=tel,
            email=email
        )

        if request.user.default_address is None:
            request.user.default_address = address
            request.user.save()

        address_dict = {
            'id': address.id,
            'title': address.title,
            "receiver": address.receiver,
            "province": address.province.name,
            "city": address.city.name,
            "district": address.district.name,
            "place": address.place,
            "mobile": address.mobile,
            "tel": address.tel,
            "email": address.email
        }
        return JsonResponse({'code': 0, 'errmsg': 'ok', 'address': address_dict})


class AddressListView(LoginRequiredJSONMixin, View):
    def get(self, request):
        addresses = Address.objects.filter(user=request.user, is_deleted=False)
        addresses_list = []
        for address in addresses:
            addresses_list.append({
                'id': address.id,
                "title": address.title,
                "receiver": address.receiver,
                "province": address.province.name,
                "city": address.city.name,
                "district": address.district.name,
                "place": address.place,
                "mobile": address.mobile,
                "tel": address.tel,
                "email": address.email
            })
        return JsonResponse({
            'code': 0, 'errmsg': 'ok', 'addresses': addresses_list,
            'default_address_id': request.user.default_address_id
        })


from utils.user import LoginRequiredJSONMixin


class UpdateDestroyAddressView(LoginRequiredJSONMixin, View):

    def put(self, request, address_id):
        json_dict = json.loads(request.body.decode())
        receiver = json_dict.get('receiver')
        province_id = json_dict.get('province_id')
        city_id = json_dict.get('city_id')
        district_id = json_dict.get('district_id')
        place = json_dict.get('place')
        mobile = json_dict.get('mobile')
        tel = json_dict.get('tel')
        email = json_dict.get('email')

        # 校验参数
        if not all([receiver, province_id, city_id, district_id, place, mobile]):
            return JsonResponse({'code': 400,
                                 'errmsg': '缺少必传参数'})

        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return JsonResponse({'code': 400,
                                 'errmsg': '参数mobile有误'})

        if tel:
            if not re.match(r'^(0[0-9]{2,3}-)?([2-9][0-9]{6,7})+(-[0-9]{1,4})?$', tel):
                return JsonResponse({'code': 400,
                                     'errmsg': '参数tel有误'})
        if email:
            if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
                return JsonResponse({'code': 400,
                                     'errmsg': '参数email有误'})

        try:
            Address.objects.filter(id=address_id).update(
                user=request.user,
                title=receiver,
                receiver=receiver,
                province_id=province_id,
                city_id=city_id,
                district_id=district_id,
                place=place,
                mobile=mobile,
                tel=tel,
                email=email
            )
        except Exception as e:
            return JsonResponse({'code': 400, 'errmsg': '更新地址失败'})

        address = Address.objects.get(id=address_id)
        addresses_dict = {
            "id": address.id,
            "title": address.title,
            "receiver": address.receiver,
            "province": address.province.name,
            "city": address.city.name,
            "district": address.district.name,
            "place": address.place,
            "mobile": address.mobile,
            "tel": address.tel,
            "email": address.email
        }
        return JsonResponse({'code': 0, 'errmsg': '更新成功', 'address': addresses_dict})

    def delete(self, request, address_id):
        try:
            addresses = Address.objects.get(id=address_id)
            addresses.is_deleted = True
            addresses.save()
        except Exception as e:
            print(e)
            return JsonResponse({'code': 400, 'errmsg': '删除地址失败'})

            # 响应删除地址结果
        return JsonResponse({'code': 0, 'errmsg': '删除地址成功'})


class DefaultAddressView(LoginRequiredJSONMixin, View):
    """设置默认地址"""

    def put(self, request, address_id):
        try:

            address = Address.objects.get(id=address_id)

            request.user.default_address = address
            request.user.save()

        except Exception as e:
            return JsonResponse({'code': 400, 'errmsg': '设置错误'})

        # 响应设置默认地址结果
        return JsonResponse({'code': 0, 'errmsg': '设置默认地址成功'})


class UpdateTitleAddressView(LoginRequiredJSONMixin, View):
    def put(self, request, address_id):
        data = json.loads(request.body.decode())
        try:
            addresses = Address.objects.get(id=address_id)
            addresses.title = data.get('title')
            addresses.save()

        except Exception as e:

            return JsonResponse({'code': 400, 'errmsg': '保存失败'})

        return JsonResponse({'code': 0, 'errmsg': '保存成功'})


from apps.users.models import User


class UpdatePwdView(LoginRequiredJSONMixin, View):
    def put(self, request):
        pwd_data = json.loads(request.body.decode())

        old_password = pwd_data.get('old_password')
        new_password = pwd_data.get('new_password')
        new_password2 = pwd_data.get('new_password2')

        # 验证参数
        if not all([old_password, new_password, new_password2]):
            return JsonResponse({'code': 400, 'errmsg': '参数不全'})

        result = request.user.check_password(old_password)

        if not result:
            return JsonResponse({'code': 400, 'errmsg': '原密码不正确'})

        if not re.match('[0-9a-zA-Z]{8,20}', new_password):
            return JsonResponse({'code': 400, 'errmsg': '密码不符合规范'})

        if new_password != new_password2:
            return JsonResponse({'code': 400, 'errmsg': '两次密码不一致'})

        try:
            request.user.set_password(new_password)
            request.user.save()

        except Exception as e:
            return JsonResponse({'code': 400, 'errmsg': '更新失败'})

        from django.contrib.auth import logout
        logout(request)

        response = JsonResponse({'code': 0, 'errmsg': 'ok'})

        return response


"""
http://doc.redisfans.com/

需求:
    添加浏览记录  -- redis    list

前端:
    登录用户,访问某一个SKU的时候,发送一个访问请求.携带 商品id

后端:

    请求:
                POST        browse_histories    sku_id 在body中
    业务逻辑:
            1. 接收请求
            2. 提取参数
            3. 验证参数
            4. 数据入库
                4.1 先去重
                4.2 再添加
                4.3 保证列表中有5条浏览记录
            5. 返回响应

    响应:
            code:0


"""

from apps.goods.models import SKU
from django_redis import get_redis_connection


class UserHistoryView(LoginRequiredJSONMixin, View):
    def post(self, request):
        user = request.user

        # 1. 接收请求
        data = json.loads(request.body.decode())
        # 2. 提取参数
        sku_id = data.get('sku_id')
        # 3. 验证参数
        try:
            sku = SKU.objects.get(id=sku_id)
        except SKU.DoesNotExist:
            return JsonResponse({'code': 400,
                                 'errmsg': '没有此商品'})
        # 4. 数据入库
        redis_cli = get_redis_connection('history')
        #     4.1 先去重
        redis_cli.lrem(user.id, 0, sku_id)
        #     4.2 再添加
        redis_cli.lpush(user.id, sku.id)
        #     4.3 保证列表中有5条浏览记录
        redis_cli.ltrim(user.id, 0, 4)
        # 5. 返回响应
        return JsonResponse({'code': 0})

    def get(self, requset):
        user = requset.user
        # 1.根据需求查询数据list[1, 32, 3, 4]
        redis_cli = get_redis_connection('history')

        ids = redis_cli.lrange(user.id, 0, -1)
        data_list = []
        for id in ids:
            # 2.根据id查询商品信息
            sku = SKU.objects.get(id=id)
            # 3.将商品信息对象转换为字典数据
            data_list.append({
                'id': sku.id,
                'name': sku.name,
                'price': sku.price,
                'default_image_url': sku.default_image.url
            })
        # 4. 返回响应
        return JsonResponse({'code': 0, 'errmsg': 'ok', "skus": data_list})


"""
需求:
        展示用户浏览记录

前端:
        发送请求.携带 cookie中的  sessionid

后端:

    请求:
            GET 
    业务逻辑:
        1.根据需求查询数据  list        [1,32,3,4]
        2.根据id查询商品信息
        3.将商品信息对象转换为字典数据
        4. 返回响应
    响应:
        "code":"0",
        "errmsg":"OK",
        "skus":[
            {
                "id":6,
                "name":"Apple iPhone 8 Plus (A1864) 256GB 深空灰色 移动联通电信4G手机",
                "default_image_url":"http://ip/CtM3BVrRbI2ARekNAAFZsBqChgk3141998.png",
                "price":"7988.00"
            },
            ......
        ]
"""
